﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using QT.Windows.Shell;

namespace UrlChecker.Tools
{
    public partial class URL : GlassForm
    {
        #region Attributes

        private Thread myThread = null;
        private delegate void myDeleGateListView(QT.SEO.SearchResult Result, string SearchEngine, string sid, string url);
        private delegate void myDeleGateButton(bool b);
        private delegate void myDeleGateShowMsg(string txt);
        private delegate string[] myDeleGateRichTextBox();
        private static ManualResetEvent Threadmre = new ManualResetEvent(true);

        private bool IsPause = false;

        #endregion

        #region URL

        public URL()
        {
            InitializeComponent();
        }

        private void URL_FormClosing(object sender, FormClosingEventArgs e)
        {
            e.Cancel = true;
            if (myThread != null && myThread.IsAlive)
            {
                if (MessageBox.Show("正在进行检查操作，确认要退出吗？", "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
                {
                    return;
                }
                myThread.Abort();
            }
            e.Cancel = false;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            this.statusStrip1.BackColor = AeroColor;
        }

        #endregion

        #region Event

        #region Button

        #region Input

        private void btnStartCheck_Click(object sender, EventArgs e)
        {
            this.lvResult.Items.Clear();
            SetCheck(false);
            myThread = new Thread(new ThreadStart(ThreadCheck));
            myThread.Start();
            IsPause = false;
        }

        private void btnPauseCheck_Click(object sender, EventArgs e)
        {
            if (IsPause)
            {
                Threadmre.Set();
                IsPause = false;
                this.btnPauseCheck.Text = "暂停";
            }
            else
            {
                Threadmre.Reset();
                IsPause = true;
                this.btnPauseCheck.Text = "继续";
            }
        }

        private void btnCancelCheck_Click(object sender, EventArgs e)
        {
            if (myThread != null && myThread.IsAlive)
            {
                if (MessageBox.Show("正在进行检查操作，确认要退出吗？", "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
                {
                    return;
                }
                myThread.Abort();
            }
            SetCheck(true);
        }

        #endregion

        #region Gather

        private void btnStartGather_Click(object sender, EventArgs e)
        {
            this.lvResult.Items.Clear();
            SetGather(false);
            myThread = new Thread(new ThreadStart(ThreadGather));
            myThread.Start();
            IsPause = false;
        }

        private void btnPauseGather_Click(object sender, EventArgs e)
        {
            if (IsPause)
            {
                Threadmre.Set();
                IsPause = false;
                this.btnPauseGather.Text = "暂停";
            }
            else
            {
                Threadmre.Reset();
                IsPause = true;
                this.btnPauseGather.Text = "继续";
            }
        }

        private void btnCancelGather_Click(object sender, EventArgs e)
        {
            if (myThread != null && myThread.IsAlive)
            {
                if (MessageBox.Show("正在进行检查操作，确认要退出吗？", "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
                {
                    return;
                }
                myThread.Abort();
            }
            SetGather(true);
        }

        #endregion

        #endregion

        #region contextStripMenu

        private void ToolStripMenutem_ExportSelection_Click(object sender, EventArgs e)
        {
            this.saveFileDialog1.ValidateNames = true;
            this.saveFileDialog1.Filter = "日志文件(*.log)|*.log|CSV文件(*.csv)|*.csv";
            this.saveFileDialog1.FilterIndex = 1;
            this.saveFileDialog1.DefaultExt = "log";
            this.saveFileDialog1.FileName = "";
            this.saveFileDialog1.AddExtension = true;
            if (this.saveFileDialog1.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            if (saveFileDialog1.FileName.EndsWith(".csv"))
            {
                if (QT.SEO.Export.Export2CSV(this.lvResult, this.lvResult.SelectedItems, this.saveFileDialog1.FileName))
                {
                    MessageBox.Show("导出成功");
                }
                else
                {
                    MessageBox.Show("操作失败");
                    return;
                }
            }
            else
            {
                if (QT.SEO.Export.Export2Txt(this.lvResult, this.lvResult.SelectedItems, this.saveFileDialog1.FileName))
                {
                    MessageBox.Show("导出成功");
                }
                else
                {
                    MessageBox.Show("操作失败");
                    return;
                }
            }
        }

        private void ToolStripMenuItem_ExportAll_Click_1(object sender, EventArgs e)
        {
            this.saveFileDialog1.ValidateNames = true;
            this.saveFileDialog1.Filter = "日志文件(*.log)|*.log|CSV文件(*.csv)|*.csv";
            this.saveFileDialog1.FilterIndex = 1;
            this.saveFileDialog1.DefaultExt = "log";
            this.saveFileDialog1.FileName = "";
            this.saveFileDialog1.AddExtension = true;
            if (this.saveFileDialog1.ShowDialog() == DialogResult.Cancel)
            {
                return;
            }

            if (saveFileDialog1.FileName.EndsWith(".csv"))
            {
                if (QT.SEO.Export.Export2CSV(this.lvResult, this.saveFileDialog1.FileName))
                {
                    MessageBox.Show("导出成功");
                }
                else
                {
                    MessageBox.Show("操作失败");
                    return;
                }
            }
            else
            {
                if (QT.SEO.Export.Export2Txt(this.lvResult, this.saveFileDialog1.FileName))
                {
                    MessageBox.Show("导出成功");
                }
                else
                {
                    MessageBox.Show("操作失败");
                    return;
                }
            }
        }

        private void ToolStripMenuItem_ImportSelection_Click(object sender, EventArgs e)
        {
            if (this.lvResult.SelectedItems.Count == 0)
            {
                MessageBox.Show("请选择要导入的记录");
                return;
            }

            ImportUrl myUrl = new ImportUrl(1);
            myUrl.Owner = this;
            myUrl.ShowDialog();
            myUrl.Dispose();
            
        }

        private void ToolStripMenuItem_ImportAll_Click(object sender, EventArgs e)
        {
            if (this.lvResult.Items.Count == 0)
            {
                MessageBox.Show("未找到任何记录");
                return;
            }

            ImportUrl myUrl = new ImportUrl();
            myUrl.Owner = this;
            myUrl.ShowDialog();
            myUrl.Dispose();
        }

        #endregion

        #region ListView

        private void lvResult_MouseClick(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Left)
            {
                ListViewItem item = ((CustomListView)sender).GetItemAt(e.X, e.Y);
                ListViewItem.ListViewSubItem portSubItem = item.GetSubItemAt(e.X, e.Y);
                int intColIndex = item.SubItems.IndexOf(portSubItem);//这个就是列索引了
                switch (intColIndex)
                {
                    case 1:
                        if (item.SubItems[intColIndex].Text.Length > 0) System.Diagnostics.Process.Start((item.SubItems[intColIndex].Text.StartsWith("http://") ? "" : "http://") + item.SubItems[intColIndex].Text);
                        break;
                    case 2://打开网页
                        if (item.SubItems[intColIndex].Text.Length > 0) System.Diagnostics.Process.Start((item.SubItems[intColIndex - 1].Text.StartsWith("http://") ? "" : "http://") + item.SubItems[intColIndex - 1].Text);
                        break;
                    case 3://打开快照页面
                        if (item.SubItems[5].Text.Length > 0) System.Diagnostics.Process.Start((item.SubItems[5].Text.StartsWith("http://") ? "" : "http://") + item.SubItems[5].Text);
                        break;
                    case 4://打开搜索页面
                        if (item.SubItems[5].Text.Length == 0)
                        {
                            if (MessageBox.Show("该网址没有快照，确认要查看搜索结果吗？", "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.Cancel)
                            {
                                return; 
                            }
                        }
                        System.Diagnostics.Process.Start((item.SubItems[6].Text.StartsWith("http://") ? "" : "http://") + item.SubItems[6].Text);
                        break;
                    default:
                        break;
                }
            }
        }

        #endregion

        #endregion

        #region Thread&DeleGate

        private void ThreadGather()
        {
            try
            {
                Threadmre.Set();

                string ref_url = "";
                string url = "";           
                List<string> urls = new List<string>();
                string[] SearchEngines = QT.SEO.Setting.Get("SearchEngine").Split('|');
                int InterVal = int.Parse(QT.SEO.Setting.Get("InterVal"));
                int Index = 0;

                showMsg(string.Format("已完成 {0}", Index));
                for (int i = (int)this.nudStart.Value; i <= (int)this.nudEnd.Value; i++)
                {
                    ref_url = url;
                    url = this.tbUrl.Text.Trim().Replace("{id}", i.ToString());
                    urls.Clear();

                    string HtmlData = QT.SEO.UrlGather.GetHtml(url, "", Encoding.Default);
                    Regex regex = new Regex(this.tbUrlRegex.Text.Trim(), RegexOptions.IgnoreCase);
                    Regex regexFilter = new Regex(this.tbUrlFilter.Text.Trim(), RegexOptions.IgnoreCase);
                    MatchCollection mc = regex.Matches(HtmlData);

                    foreach (Match mt in mc)
                    {
                        if (regexFilter.IsMatch(mt.Value)) continue;
                        urls.Add(mt.Value);
                    }                    
                    
                    foreach (string SearchEngine in SearchEngines)
                    {
                        url = "";
                        DataTable dt = QT.SEO.SearchEngine.Get(SearchEngine);
                        string myURI = dt.Rows[0]["uri"].ToString();
                        int codepage = 0;
                        if (!(int.TryParse(dt.Rows[0]["codepage"].ToString(), out codepage))) codepage = 0;
                        foreach (string myurl in urls)
                        {
                            if (string.IsNullOrEmpty(myurl)) continue;

                            ref_url = url;
                            url = myURI.Replace("{keywords}", myurl);

                            try
                            {
                                Thread.Sleep(InterVal * 1000);

                                string myHtml = QT.SEO.UrlGather.GetHtml(url, ref_url, Encoding.GetEncoding(codepage)).Replace(" ", "").Replace("\n", "").Replace("\r", "");
                                QT.SEO.SearchResult Result = new QT.SEO.SearchResult();
                                Result = QT.SEO.UrlGather.GetSnapShot(myHtml, dt.Rows[0], myurl, Encoding.GetEncoding(codepage));
                                Threadmre.WaitOne();
                                myDeleGateListView myDelegate = new myDeleGateListView(SaveResult);
                                this.Invoke(myDelegate, Result, dt.Rows[0]["SearchName"].ToString(), SearchEngine, url);
                                Index++;
                                showMsg(string.Format("已完成 {0}", Index));
                            }
                            catch
                            {
                                continue;
                            }
                        }

                        dt.Dispose();
                    }
                }

                this.Invoke(new myDeleGateButton(SetGather), new object[] { true });
            }
            catch (ThreadAbortException)
            {
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        private void ThreadCheck()
        {
            try
            {
                string[] SearchEngines = QT.SEO.Setting.Get("SearchEngine").Split('|');
                int InterVal = int.Parse(QT.SEO.Setting.Get("InterVal"));
                int myCount = (SearchEngines.Length) * (GetList().Length);
                int Index = 0;
                showMsg(string.Format("已完成 {0}/{1}", Index, myCount));
                foreach (string SearchEngine in SearchEngines)
                {
                    DataTable dt = QT.SEO.SearchEngine.Get(SearchEngine);
                    string myURI = dt.Rows[0]["uri"].ToString();
                    int codepage = 0;
                    if (!(int.TryParse(dt.Rows[0]["codepage"].ToString(), out codepage))) codepage = 0;
                    string ref_url = "";
                    string url = "";
                    string[] lines = GetList();
                    foreach (string myurl in lines)
                    {
                        if (string.IsNullOrEmpty(myurl)) continue;

                        ref_url = url;
                        url = myURI.Replace("{keywords}", myurl);

                        try
                        {
                            Thread.Sleep(InterVal * 1000);

                            string myHtml = QT.SEO.UrlGather.GetHtml(url, ref_url, Encoding.GetEncoding(codepage)).Replace(" ", "").Replace("\n", "").Replace("\r", "");
                            QT.SEO.SearchResult Result = new QT.SEO.SearchResult();
                            Result = QT.SEO.UrlGather.GetSnapShot(myHtml, dt.Rows[0], myurl,Encoding.GetEncoding(codepage));
                            Threadmre.WaitOne();
                            myDeleGateListView myDelegate = new myDeleGateListView(SaveResult);
                            this.Invoke(myDelegate, Result, dt.Rows[0]["SearchName"].ToString(), SearchEngine, url);
                            Index++;
                            showMsg(string.Format("已完成 {0}/{1}", Index, myCount));
                        }
                        catch
                        {
                            continue;
                        }
                    }

                    dt.Dispose();
                }

                this.Invoke(new myDeleGateButton(SetCheck), new object[] { true });
            }
            catch (ThreadAbortException)
            {
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }

        #endregion

        #region ListView

        private void SaveResult(QT.SEO.SearchResult Result, string SearchEngine, string sid,string url)
        {
            ListViewItem item = new ListViewItem();
            item.SubItems[0].Text = (this.lvResult.Items.Count + 1).ToString();
            item.SubItems.Add(Result.url);
            item.SubItems.Add(Result.title);
            item.SubItems.Add(Result.date);
            item.SubItems.Add(SearchEngine);
            item.SubItems.Add(Result.snapshot); //快照URL
            item.SubItems.Add(url); //搜索URL
            item.SubItems.Add(sid); //搜索引擎ID

            item.UseItemStyleForSubItems = true;
            if (Result.IsSnap == false)
            {
                item.ForeColor = Color.Red;
            }
            this.lvResult.Items.Add(item);
        }

        #endregion

        #region Method

        private void SetCheck(bool b)
        {
            this.rtbList.Enabled = b;
            this.btnStartCheck.Enabled = b;
            this.btnPauseCheck.Enabled = !b;
            this.btnCancelCheck.Enabled = !b;
            this.pCollect.Enabled = b;
        }

        private void SetGather(bool b)
        {
            this.btnStartGather.Enabled = b;
            this.btnPauseGather.Enabled = !b;
            this.btnCancelGather.Enabled = !b;
            this.pInput.Enabled = b;
        }

        private string[] GetList()
        {
            if (this.InvokeRequired)
            {
                return this.Invoke(new myDeleGateRichTextBox(GetList)) as string[];
            }
            else
            {
                string[] strUrl = this.rtbList.Lines; 
                return strUrl;
            }
        }

        private void showMsg(string txt)
        {
            if (this.InvokeRequired)
            {
                this.Invoke(new myDeleGateShowMsg(showMsg), new object[] { txt });
            }
            else
            {
                this.tsslMsg.Text = txt;
            }
        }

        #endregion
    }

    public struct SearchResult
    {
        public string url;
        public string title;
        public string date;
    }

    public class CustomListView : ListView
    {
        public CustomListView()
        {
            SetStyle(ControlStyles.DoubleBuffer | ControlStyles.OptimizedDoubleBuffer | ControlStyles.AllPaintingInWmPaint, true);
            UpdateStyles();
        }
    }
}
